package star.cloud.asme.base.mybatis;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import star.cloud.asme.base.dto.Result;
import star.cloud.asme.flowable.form.FormBaseEntity;
import star.cloud.asme.flowable.processInstance.DTO.StartProcessInstanceParams;
import star.cloud.asme.system.user.UserMapper;

import java.time.LocalDate;
import java.util.List;


@Slf4j
public abstract class IBaseServiceImpl<M extends IBaseMapper<T>, T extends IBaseEntity<T>> extends ServiceImpl<IBaseMapper<T>, T> implements IBaseService<T> {

    @Autowired
    private IBaseMapper<T> iBaseMapper;

    @Autowired
    private UserMapper userMapper;

    @Override
    public Result<T> getOneByCondition(String columnName, Object columnValue) {
        T t = iBaseMapper.selectOne(new QueryWrapper<T>().eq(StringUtils.camelToUnderline(columnName), columnValue));
        if (t != null) {
            setCreatorAndUpdater(t);
        }
        return Result.ok(t);
    }

    @Override
    public Result<List<T>> getListByCondition(String columnName, Object columnValue) {
        return Result.ok(iBaseMapper.selectList(new QueryWrapper<T>().eq(StringUtils.camelToUnderline(columnName), columnValue)));
    }

    @Override
    public Result<List<T>> getListByConditions(T conditions) {
        return Result.ok(iBaseMapper.selectList(null));
    }

    @Override
    public Result<IPage<T>> getListByConditionsWithPage(T conditions) {
        IPage<T> iPage = new Page<>(conditions.getCurrentPage(), conditions.getPageSize());
        iBaseMapper.selectPage(iPage, null);
        return Result.ok(iPage);
    }

    @Override
    public Result<T> insertOne(T entity) {
        return iBaseMapper.insert(entity) > 0 ? Result.ok(entity) : Result.error(entity);
    }

    @Override
    public Result<?> physicalDeleteById(Long id) {
        return iBaseMapper.physicalDeleteById(id) > 0 ? Result.ok().msg("停用成功") : Result.error().msg("停用失败");
    }

    @Override
    public Result<?> logicalDeleteById(Long id) {
        return iBaseMapper.deleteById(id) > 0 ? Result.ok().msg("停用成功") : Result.error().msg("停用失败");
    }

    @Override
    public Result<?> activeById(Long id) {
        return iBaseMapper.activeById(id) > 0 ? Result.ok().msg("激活成功") : Result.error().msg("激活");
    }

    @Override
    public Result<T> updateOne(T entity) {
        return this.updateById(entity) ? Result.ok(entity).msg("更新成功") : Result.error(entity).msg("更新失败");
    }

    @Override
    public void setCreatorAndUpdater(T entity) {
        entity.setCreator(userMapper.selectById(entity.getCreatorId()));
        entity.setUpdater(userMapper.selectById(entity.getUpdaterId()));
    }

    @Override
    public void setCreatorAndUpdater(IPage<T> iPage) {
        iPage.getRecords().forEach(this::setCreatorAndUpdater);
    }

    @Override
    public StartProcessInstanceParams generateStartProcessInstanceParams(FormBaseEntity<T> entity) {
        StartProcessInstanceParams.StartProcessInstanceParamsBuilder paramsBuilder = StartProcessInstanceParams.builder();
        paramsBuilder.processDefinitionId(entity.getProcessDefinitionId());
        paramsBuilder.processDefinitionKey(entity.getProcessDefinitionKey());
        paramsBuilder.loginUsername(entity.getCreator().getUsername());
        paramsBuilder.businessKey(String.valueOf(entity.getId()));
        paramsBuilder.processInstanceName(entity.getProcessInstanceName());
        paramsBuilder.variables(entity.getVariables());
        return paramsBuilder.build();
    }

    @Override
    public void setProcessInstanceInfo(FormBaseEntity<T> entity, ProcessInstance processInstance) {
        entity.setProcessInstanceId(processInstance.getId());
        entity.setProcessDefinitionId(processInstance.getProcessDefinitionId());
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("create_time", LocalDate.now());
        List<T> leaveList = iBaseMapper.selectList(queryWrapper);
        if (leaveList.isEmpty()) {
            entity.setBusinessFlowId(1);
        } else {
            entity.setBusinessFlowId(leaveList.size());
        }
        String businessId = processInstance.getProcessDefinitionKey() + "-" + LocalDate.now().getYear() + LocalDate.now().getMonthValue() + LocalDate.now().getDayOfMonth() + "-" + String.format("%04d", entity.getBusinessFlowId());
        entity.setBusinessId(businessId);
    }

    @Override
    public boolean updateById(T entity) {
        setVersion(entity);
        return iBaseMapper.updateById(entity) > 0;
    }


}